package yycore

import chisel3._
import chisel3.util._
import common.Constants._
import bus._
import utils.PipelineConnect



class Backend extends Module {
  val io = IO(new Bundle(){
    val flush = Output(Vec(2, Bool()))
    val in = Flipped(Decoupled(new InstrPackage))
    val dmem = new CoreLinkIO(DataBits)
    val mmio = new CoreLinkIO(DataBits)
    // val ctrl = new EndCtrlIO
    val redirect = new RedirectIO
  })

  val s_dec = Module(new DecodeStage())
  val s_exe = Module(new EXEStage())
  val s_wb = Module(new WBUStage)
  val GPR = Module(new GPRs())

  io.dmem <> s_exe.io.dmem
  io.mmio <> s_exe.io.mmio
  io.redirect <> s_wb.io.redirect

  s_dec.io.in <> io.in
  s_dec.io.r_reg <> GPR.io.r

  val flush = s_wb.io.redirect.valid
  s_dec.io.flush := flush
  s_exe.io.flush := flush
  s_wb.io.flush := flush
  io.flush.map(_ := flush)

  PipelineConnect(s_dec.io.out, s_exe.io.in,
    update = s_exe.io.in.fire() && s_exe.io.out.fire() && !flush,
    flush = (!s_exe.io.in.fire() && s_exe.io.out.fire()) || flush)

  s_wb.io.in <> s_exe.io.out
  s_wb.io.w_reg <> GPR.io.w




  // bypass
  s_dec.io.bypass(0) <> s_exe.io.bypass
  s_dec.io.bypass(1) <> s_wb.io.bypass
}


